Vue 之 解决v 您所在的位置:网站首页 onclick html Vue 之 解决v

Vue 之 解决v

#Vue 之 解决v| 来源: 网络整理| 查看: 265

一、简介 官方文档:

在这里插入图片描述 通过上面官方文档的介绍我们可以得知两个重点:

① 通过v-html生成的页面元素,不会被当做Vue模板进行编译,只会作为普通的html代码被插入,也就是说通过v-html插入的html代码中,如果包含vue的语法,例如:@click、v-if等,则不会生效,因为他们没有被Vue编译,而浏览器并不会识别这些vue语法,所以这些语法都不生效。

② 在.vue文件中如果style标签上增加了scoped属性,那么该标签内的样式就不会对v-html生成的页面元素起作用,还是因为这些元素没有被当做Vue模板进行编译,所以不生效。

如果在某些业务场景下我们给v-html生成的页面元素绑定了@click事件,需要触发某些处理方法,或者需要给这些元素设置CSS样式时,这两个问题就比较致命了,所以我们要想办法去解决这俩问题。

解决绑定事件失效方法有:使用onclick等原生事件代替@click等事件vue事件、利用事件委托触发事件、使用component模板代替v-html。

解决样式不生效的方法有:/deep/、::v-deep、>>> 、:deep、额外的全局。

二、解决@click等vue事件不触发 1、使用onclick等原生事件代替@click等vue事件

思路: vue事件之所以不能被触发是因为,v-html生成的页面元素,是在Vue文件编译之后插入到页面中的,不会被Vue编译,只会作为普通的html代码被插入,所以无法识别vue事件。既然是普通的html代码,那我们可以使用原生的事件去代替vue事件,原生事件一定会被触发,但此时又出现一个新问题,那就是原生事件被触发后,无法访问到vue实例的data中的数据和methods中的方法,究其原因还是由于没有被vue编译的问题。 既然问题出现了,那就想办法解决问题。既然访问不到vue实例中的数据和方法,那么我们可以将事件所需要使用的数据和方法,挂载在window对象上,这样就可以被原生事件访问到了。

具体代码: export default { data() { return { // 富文本数据 将原来的@click改为使用onclick html: '这是v-html渲染的元素 点击按钮', a: '这是个变量' } }, mounted() { // 将vue实例的方法绑定到window对象中去 window.btnClick = this.btnClick }, methods: { btnClick() { alert('点击事件触发成功 + '+ this.a) } } }

调用结果:

在这里插入图片描述

结论: 这种方法在一定程度上解决了v-html渲染元素不能触发@click的问题,但同样限制条件也比较多,比如:如果通过v-for同时渲染大量相似数据,无法访问当前循环项的数据,也就无法区分不同循环项的数据。所以这种方法只适用于绑定比较简单的事件处理操作。

2、利用事件委托触发事件

思路: 这种方法的原理是将子元素要触发执行的事件绑定到父元素上,点击子元素触发事件将会冒泡到父元素,然后父元素去执行对应的事件处理函数,但是要注意在事件处理函数中通过e.target去判断,触发事件的元素是不是我们想要绑定的那个元素,只有是目标子元素时,才去执行事件处理逻辑。

具体代码: export default { name: 'HelloWorld', data() { return { // 富文本数据 目标子元素为button按钮 html: '这是通过v-html渲染的元素 点击按钮', a: '这是个变量' } }, methods: { btnClick(e) { // 判断当前触发事件的元素 是不是目标子元素 if(e.target.id === 'btn') alert('点击按钮事件触发成功 + '+ this.a) } } } 调用结果:

在这里插入图片描述 结论: 这种方法比较好,不需要对富文本数据进行修改,也不需要修改window对象,比较推荐。

3、使用component模板代替v-html

思路: 前面我们已经得知@click等vue时间之所以不起作用,是因为v-html渲染的数据是在不会被当做Vue模板进行编译,只会作为普通的html代码被插入,那我们就想一种可以被当成Vue模板的渲染方式,那就是通过component模板来进行渲染。需要引入vue,通过Vue.extend(options) 基础Vue构造器,创建一个“子类”,然后通过vm.$mount()将实例进行编译,最后通过原生js进行挂载。

具体代码: 父组件 import Vue from 'vue' export default { name: 'HelloWorld', data() { return { a: '这是a变量' } }, mounted() { // 使用变量暂存一下this指向的vue实例 var that = this; // 通过Vue.extend创建子类组件 var MyComponent = Vue.extend({ template: '这是通过v-html渲染的元素 点击按钮', methods: { add() { // 通过暂存的that获取当前实例的数据和方法 alert('触发了点击事件,并访问当时vue实例的变量a: ' + that.a) that.btnClick() } } }) // 通过 $mount() 将子类组件进行编译 let component=new MyComponent().$mount() // 通过原生js进行挂载 document.getElementById('parent').appendChild(component.$el); }, methods: { btnClick() { alert('点击按钮触发当时vue实例成功') } } } 调用结果:

在这里插入图片描述 在这里插入图片描述 结论: 这种方法看起来比较高端,确实也比较好用,但是不适用于大量数据的渲染,因为会创建过多的vue子类,占用大量内存。

3、解决样式不生效的问题

请查看:vue 之 CSS进行样式穿透的方法(/deep/、::v-deep、>>> 、:deep、额外的全局<style>)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有